
import 'package:flutter/foundation.dart';
import 'package:json_annotation/json_annotation.dart';

@JsonSerializable()
abstract class MessageContent{

  const MessageContent();

  /// Converts a text message to the map representation, encodable to JSON.
  Map<String, dynamic> toJson();

  static fromJson(Map<String, dynamic> json) {

  }
}

@JsonSerializable()
@immutable
class TextMessageContent extends MessageContent{

  /// User's message.
  final String text;

  const TextMessageContent._(this.text);

  const TextMessageContent.fromParams(this.text);

  factory TextMessageContent.fromJson(Map<String, dynamic> json) => TextMessageContent
      ._(json['text'] as String);

  /// Converts a text message to the map representation, encodable to JSON.
  @override
  Map<String, dynamic> toJson(){
    final val = <String, dynamic>{
    };
    void writeNotNull(String key, dynamic value) {
      if (value != null) {
        val[key] = value;
      }
    }
    writeNotNull('text',this.text);
    return val;
  }
}

@JsonSerializable()
@immutable
class VideoMessageContent extends MessageContent{

  /// The name of the video.
  final String name;

  /// Video width in pixels.
  final double? width;

  /// Video height in pixels.
  final double? height;


  /// Size of the video in bytes.
  final num size;

  /// The video source (either a remote URL or a local resource).
  final String uri;

  const VideoMessageContent._(this.name, this.width, this.height, this.size, this.uri);

  const VideoMessageContent.fromParams(this.name, this.width, this.height, this.size, this.uri);

  factory  VideoMessageContent.fromJson(Map<String,dynamic> json)
  =>VideoMessageContent._(json['name'], json['width'], json['height'], json['size'] ,json['uri'] );

  @override
  Map<String, dynamic> toJson(){
    final val = <String, dynamic>{
    };
    void writeNotNull(String key, dynamic value) {
      if (value != null) {
        val[key] = value;
      }
    }
    writeNotNull('name',this.name);
    return val;
  }

}


@JsonSerializable()
@immutable
class ImageMessageContent extends  MessageContent {

  /// Image height in pixels.
  final double? height;

  /// The name of the image.
  final String name;

  /// Size of the image in bytes.
  final num size;

  /// The image source (either a remote URL or a local resource).
  final String uri;

  /// Image width in pixels.
  final double? width;

  const ImageMessageContent._(this.name,this.width,this.height,this.size,this.uri);

  const ImageMessageContent.fromParams(this.name,this.width,this.height,this.size,this.uri);

  factory ImageMessageContent.fromJson(Map<String,dynamic> json)=>
      ImageMessageContent._(json['name'], json['width'], json['height'], json['size'] ,json['uri'] );


  @override
  Map<String, dynamic> toJson(){
    final val = <String, dynamic>{
    };
    void writeNotNull(String key, dynamic value) {
      if (value != null) {
        val[key] = value;
      }
    }
    writeNotNull('name',this.name);
    return val;
  }

}

@JsonSerializable()
@immutable
class AudioMessageContent extends MessageContent{
  /// The length of the audio.
  final Duration duration;

  /// Media type of the audio file.
  final String? mimeType;

  /// The name of the audio.
  final String name;

  /// Size of the audio in bytes.
  final num size;

  /// The audio file source (either a remote URL or a local resource).
  final String uri;

  /// Wave form represented as a list of decibel levels.
  final List<double>? waveForm;

  const AudioMessageContent._(this.duration, this.mimeType, this.name, this.size, this.uri, this.waveForm);

  const AudioMessageContent.fromParams(this.duration, this.mimeType, this.name, this.size, this.uri, this.waveForm);

  factory AudioMessageContent.fromJson(Map<String,dynamic> json)=>
      AudioMessageContent._(json['duration'], json['mimeType'], json['name'], json['size'], json['url'], json['waveForm']);

  @override
  Map<String, dynamic> toJson(){
    final val = <String, dynamic>{
    };
    void writeNotNull(String key, dynamic value) {
      if (value != null) {
        val[key] = value;
      }
    }
    writeNotNull('name',this.name);
    return val;
  }
}